# coding=utf-8
from socket import *
import Setting
import redis
import threading
import requests
import time
import sys
reload(sys) # Python2.5 初始化后删除了 sys.setdefaultencoding 方法，我们需要重新载入 
sys.setdefaultencoding('utf-8') 

def get_wait():
    while True:
        wait = r.rpop('waitUpProduct')
        if not wait:
            return False
        else:
            wait = wait.decode('utf-8')
            wait_hash = r.hgetall(wait)
            info = str()
            info = 'id:@:'+wait.split('_')[-1]

            for key, value in wait_hash.items():
                if key.decode('utf-8') == 'Sessinkey':
                    info += ',Sessinkey:@:' + value.decode('utf-8')
                else:
                    info += "," + key.decode('utf-8') + ":@:" + value.decode('utf-8')

            return info

def inform_api(info_dict):
    goods_id = info_dict.pop('goods')
    pictureid = info_dict.pop('pictureid')
    goods_name = 'EndUpProduct_' + goods_id
    
    r.lpush('delpicidlist', pictureid)
    r.hmset(goods_name, info_dict)
    response = requests.get(Setting.api+goods_id)
    print(response)


def lost_task(wait):
    """把丢失的任务回来放在任务队列里"""
    a = wait.split(",")
    a = a[0].split(":@:")
    a = a[1]
    
    info = 'wait_product_%s'%a

    wait = r.lpush('waitUpProduct', info)


def new_client(client_socket, index):
    """建立一个客户端为ｗｏｒｋ工作"""

    print '正在执行，执行任务次数：', index
    
    while True:
        wait = get_wait()

        if not wait:
            print "没有检测到任务，返回worker让它继续等待"
            try:
                client_socket.send('not task'.encode('utf-8'))
            except Exception as e:
                print "发送错误，应该是客户端断连了", e
            recv_data = client_socket.recv(1024)  # 接收1024个字节
            
            if not recv_data:
                print "失去一个客户端"
                client_socket.close()
                return

            print '接收到的数据为:', recv_data.decode('utf-8')
        else:
            break
            
    
    try:
        # 发送任务到客户端
        client_socket.send(wait.encode('utf-8'))
    except Exception as e:
        print "发送错误，应该是客户端断连了", e
    
    # 接收对方发送过来的数据
    recv_data = client_socket.recv(1024)  # 接收1024个字节
    if not recv_data:
        print "失去一个客户端"
        client_socket.close()

        # 把丢失任务回流
        lost_task(wait) 
        return

    print '接收到的数据为:', recv_data.decode('utf-8')
    client_socket.send('sendend'.encode('utf-8'))
    print '任务发送完毕', index
    
    start = time.time()
    
    with open('执行任务记录.txt', 'a') as f:
        f.write('任务序号:'+str(index)+'开始时间:'+str(start)+'正在执行\n\n\n')
    info_dict = dict()


    # 看看任务是否丢失

    lost = False
    task_str = str()
    while True:
        
        recv_data = client_socket.recv(1024)  # 接收1024个字节
        if not recv_data:
            if not lost:
                lost_task(wait)  # 任务丢失回流
                client_socket.close()
                return
            task_str = task_str.split('*_*')
            for recv_data in task_str[0, -1]:

                recv_data = recv_data.split(',')
                
                
                if recv_data[0] == 'id':
                    info_dict[recv_data[1]] = recv_data[2]
                elif recv_data[0] == 'pictureid':
                    info_dict[recv_data[0]] = recv_data[1]
                elif recv_data[0] == 'goods':
                    info_dict[recv_data[0]] = recv_data[1]

                    inform_api(info_dict)

            break
        lost = True  #　只要第一次接收任务不是断掉链接就说明任务完成
        print(recv_data)
        
        task_str += "*_*" + recv_data

        


    client_socket.close()
    print '任务执行完毕共执行时间:', time.time()-start
    
    with open('执行任务记录.txt', 'a') as f:
        f.write('任务序号:'+str(index)+'开始时间:'+str(start)+'共执行时间:'+str(time.time()-start)+'\n\n\n')
    return


def main():
    # 创建socket
    tcp_server_socket = socket(AF_INET, SOCK_STREAM)

    # 本地信息
    address = (Setting.ServerIp, Setting.ServerPort)

    # 绑定
    tcp_server_socket.bind(address)

    # 使用socket创建的套接字默认的属性是主动的，使用listen将其变为被动的，这样就可以接收别人的链接了
    tcp_server_socket.listen(128)
    global index

    while True:

        # 如果有新的客户端来链接服务器，那么就产生一个新的套接字专门为这个客户端服务
        # client_socket用来为这个客户端服务
        # tcp_server_socket就可以省下来专门等待其他新客户端的链接
        client_socket, clientAddr = tcp_server_socket.accept()
        t = threading.Thread(target=new_client, args=(client_socket, index))
        t.start()
        index += 1

    # 关闭为这个客户端服务的套接字，只要关闭了，就意味着为不能再为这个客户端服务了，如果还需要服务，只能再次重新连接
    client_socket.close()

index = 1
r = redis.StrictRedis(host='localhost', port=6379, db=0)
if __name__ == '__main__':
    print '启动服务器成功'
    main()
